package br.ufrj.dcc.ad.simulador;

import java.util.LinkedList;
import java.util.Queue;

import br.ufrj.dcc.ad.cliente.Cliente;
import br.ufrj.dcc.ad.evento.Evento;
import br.ufrj.dcc.ad.evento.TipoEvento;
import br.ufrj.dcc.ad.gerador.GeradorTempoEventos;
import br.ufrj.dcc.ad.gerador.GeradorTempoEventosExponencial;

public class SimuladorMG1 extends Simulador{
	private int numeroClientesFila;
	private GeradorTempoEventos geradorServico;
	private GeradorTempoEventos geradorChegadas;
	private double tempoDecorridoDesdeInicioSimulacao;
	private Queue<Cliente> filaEspera;

	public SimuladorMG1(GeradorTempoEventos geradorServico, double lambda) {
		this.geradorServico = geradorServico;
		this.inicializaFilaEventos(lambda);
		
	}
	
	private void inicializaFilaEventos(double lambda){
		super.eventos = new LinkedList<Evento>();
		this.filaEspera = new LinkedList<Cliente>();
		this.numeroClientesFila = 0;
		this.tempoDecorridoDesdeInicioSimulacao = 0.0;
		this.geradorChegadas = new GeradorTempoEventosExponencial(lambda);
		
		Evento primeiraChegada = this.geraNovaChegada();
		this.eventos.add(primeiraChegada);
	}

	@Override
	protected void trataEvento(Evento e) {
		switch(e.getTipoEvento()){
			case CHEGADA:
				this.trataChegada(e);
				break;
			case PARTIDA:
				this.trataPartida(e);
				break;
		}
	}
	
	private void trataChegada(Evento e){
		Evento novaChegada = this.geraNovaChegada();
		this.eventos.add(novaChegada);
		
		Cliente novoCliente = new Cliente(this.numeroClientesFila);
		novoCliente.setTempoChegada(novaChegada.getTempoEvento());
		
		this.numeroClientesFila++;
		this.filaEspera.add(novoCliente);
		if(this.numeroClientesFila == 1){
			this.eventos.add(this.geraNovaPartida());
		}
		
	}
	
	private void trataPartida(Evento e){
		this.numeroClientesFila--;
		if(this.numeroClientesFila > 0){
			this.eventos.add(this.geraNovaPartida());
		}
		
		this.calculaTempoEsperaClienteAtualmenteServido();
	}
	
	private Evento geraNovaChegada(){
		return new Evento((this.tempoDecorridoDesdeInicioSimulacao += this.geradorChegadas.getTempoEntreEventos()), TipoEvento.CHEGADA);
	}
	
	private Evento geraNovaPartida(){
		return new Evento((this.tempoDecorridoDesdeInicioSimulacao += this.geradorServico.getTempoEntreEventos()), TipoEvento.PARTIDA);
	}
	
	private void calculaTempoEsperaClienteAtualmenteServido(){
		
	}

	public int getNumeroClientesFila() {
		return numeroClientesFila;
	}

	public void setNumeroClientesFila(int numeroClientesFila) {
		this.numeroClientesFila = numeroClientesFila;
	}

	public GeradorTempoEventos getGeradorServico() {
		return geradorServico;
	}

	public void setGeradorServico(GeradorTempoEventos geradorServico) {
		this.geradorServico = geradorServico;
	}
	
	
}
